<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Strict//EN">
<html>

<head>
<meta http-equiv="Content-Language" content="en-us">
<title>Plugin tutorial</title>
<link rel="stylesheet" type="text/css" href="../style.css">
</head>

<body>

<div align="center">
<table class=allEncompassingTable >
 <tr>
  <td >
<p><a href="../index.html" TARGET="_top"><img src="images/homeImg.png"></a></p>



<h1>Plugin tutorial</h1>


<p>This tutorial describes how to write a <a href="plugins.htm">plugin</a> for CoppeliaSim. The CoppeliaSim scene file related to this tutorial is located in <em>scenes/tutorials/BubbleRobExt</em>. The plugin project files of this tutorial can be found <a href="https://github.com/CoppeliaRobotics/simExtBubbleRob" target="_blank">here</a>.<br>
</p>

<p>CoppeliaSim automatically loads all plugins that it can find in its folder (i.e. the installation folder, or the same folder as the one that contains <em>coppeliaSim.exe</em>) at program start-up. CoppeliaSim recognizes plugin files with following mask: &quot;simExt*.dll&quot; on Windows, &quot;libsimExt*.dylib&quot; on Mac OS and &quot;libsimExt*.so&quot; on Linux. Additionally a plugin's filename should not contain any underscore (except the one at the beginning obviously). The plugin file of this tutorial is <em>simExtBubbleRob.dll</em>. When testing it, make sure it was properly loaded at CoppeliaSim start-up: switch the <a href="userInterface.htm#ConsoleWindow">console window</a> to visible by unchecking the <strong>Hide console window</strong> item in the <a href="settings.htm">user settings dialog</a> ([Menu bar --&gt; Tools --&gt; Settings]). This option is only available in the Windows version. On Mac, have a look at the system's console, and on Linux try to start CoppeliaSim from within a console. The console window should display something similar to this:<br>
</p>

<p align=center><img src="images/pluginTut1.jpg"></p>
<br>

<p>As you already understood, this plugin was written for BubbleRob from the <a href="bubbleRobTutorial.htm">BubbleRob tutorial</a>. Load the related scene file (<em>scenes/tutorials/BubbleRobExt/BubbleRobExt.ttt</em>). The BubbleRob plugin adds 4 new Lua commands (custom Lua commands should follow the convention: &quot;simXXX.YYY&quot; for the name, e.g. simRob.start):<br>
</p>


<h3 class=subsectionBar>simBubble.create</h3>
<table class=apiTable>
	<tr class=apiTableTr> 
		<td class=apiTableLeftDescr>
			Description 
		</td> 
		<td class=apiTableRightDescr>
			Creates an instance of a BubbleRob controller in the plugin.</td>
	</tr> 
	<tr class=apiTableTr> 
		<td class=apiTableLeftLSyn>
			Lua synopsis
		</td> 
		<td class=apiTableRightLSyn>number bubbleRobHandle=simBubble.create(table[2] motorJointHandles,number sensorHandle,table[2] backRelativeVelocities)<br></td> 
	</tr> 
	<tr class=apiTableTr> 
		<td class=apiTableLeftLParam>Lua parameters</td> 
		<td class=apiTableRightLParam>
			<div><strong>motorJointHandles</strong>: a table containing the handles of the left and right motor joints of the BubbleRob you wish to control.</div>
			<div><strong>sensorHandle</strong>: the handle of the proximity sensor or the BubbleRob you wish to control</div>
			<div><strong>backRelativeVelocities</strong>: when BubbleRob detects an obstacle, it will move backwards for some time. relativeBackVelocities[1] is the relative velocity of the left wheel when moving back. relativeBackVelocities[2] is the relative velocity of the right wheel when moving back</div>
		</td> 
	</tr> 
	<tr class=apiTableTr> 
		<td class=apiTableLeftLRet>
			Lua return values
		</td> 
		<td class=apiTableRightLRet><div>result: -1 in case of an error, otherwise the handle of the plugin's BubbleRob controller.</div>
		</td> 
	</tr> 
</table> 
<br>

<h3 class=subsectionBar>simBubble.destroy</h3>
<table class=apiTable>
	<tr class=apiTableTr> 
		<td class=apiTableLeftDescr>
			Description 
		</td> 
		<td class=apiTableRightDescr>
			Destroys an instance of a BubbleRob controller previously created with simBubble.create.</td>
	</tr> 
	<tr class=apiTableTr> 
		<td class=apiTableLeftLSyn>
			Lua synopsis
		</td> 
		<td class=apiTableRightLSyn>boolean result=simBubble.destroy(number bubbleRobHandle)</td> 
	</tr> 
	<tr class=apiTableTr> 
		<td class=apiTableLeftLParam>Lua parameters</td> 
		<td class=apiTableRightLParam>
			<div><strong>bubbleRobHandle</strong>: the handle of a BubbleRob instance previously returned from simBubble.create.</div>
		</td> 
	</tr> 
	<tr class=apiTableTr> 
		<td class=apiTableLeftLRet>
			Lua return values
		</td> 
		<td class=apiTableRightLRet><div>result: false in case of an error</div>
		</td> 
	</tr> 
</table> 
<br>

<h3 class=subsectionBar>simBubble.start</h3>
<table class=apiTable>
	<tr class=apiTableTr> 
		<td class=apiTableLeftDescr>
			Description 
		</td> 
		<td class=apiTableRightDescr>
			Sets a BubbleRob into an automatic movement mode 
		</td>
	</tr> 
	<tr class=apiTableTr> 
		<td class=apiTableLeftLSyn>
			Lua synopsis
		</td> 
		<td class=apiTableRightLSyn>boolean result=simBubble.start(number bubbleRobHandle)</td> 
	</tr> 
	<tr class=apiTableTr> 
		<td class=apiTableLeftLParam>Lua parameters</td> 
		<td class=apiTableRightLParam>
			<div><strong>bubbleRobHandle</strong>: the handle of a BubbleRob instance previously returned from simBubble.create.</div>
		</td> 
	</tr> 
	<tr class=apiTableTr> 
		<td class=apiTableLeftLRet>
			Lua return values
		</td> 
		<td class=apiTableRightLRet>
			<div><strong>result</strong>: false in case of an error</div>
		</td> 
	</tr> 
</table> 
<br>


<h3 class=subsectionBar>simBubble.stop</h3>
<table class=apiTable>
	<tr class=apiTableTr> 
		<td class=apiTableLeftDescr>
			Description 
		</td> 
		<td class=apiTableRightDescr>
			Stops the automatic movement of a BubbleRob</td>
	</tr> 
	<tr class=apiTableTr> 
		<td class=apiTableLeftLSyn>
			Lua synopsis
		</td> 
		<td class=apiTableRightLSyn>boolean result=simBubble.stop(number bubbleRobHandle)<br></td> 
	</tr> 
	<tr class=apiTableTr> 
		<td class=apiTableLeftLParam>Lua parameters</td> 
		<td class=apiTableRightLParam>
			<div><strong>bubbleRobHandle</strong>: the handle of a BubbleRob instance previously returned from simBubble.create.</div>
		</td> 
	</tr> 
	<tr class=apiTableTr> 
		<td class=apiTableLeftLRet>
			Lua return values
		</td> 
		<td class=apiTableRightLRet><div>result: false in case of an error</div>
		</td> 
	</tr> 
</table> 
<br>

<p>Now open the threaded <a href="childScripts.htm">child script</a> attached to the BubbleRob model in the scene (e.g. double-click the script icon next to object <em>bubbleRob</em> in the scene hierarchy). Inspect the code:<br>
</p>

<pre class=lightRedBox>function sysCall_init()
    corout=coroutine.create(coroutineMain)
end

function sysCall_actuation()
    if coroutine.status(corout)~='dead' then
        local ok,errorMsg=coroutine.resume(corout)
        if errorMsg then
            error(debug.traceback(corout,errorMsg),2)
        end
    end
end

function coroutineMain()
    -- Check if the required plugin is there:
    moduleName=0
    moduleVersion=0
    index=0
    bubbleRobModuleNotFound=true
    while moduleName do
        moduleName,moduleVersion=sim.getModuleName(index)
        if (moduleName=='BubbleRob') then
            bubbleRobModuleNotFound=false
        end
        index=index+1
    end
    if bubbleRobModuleNotFound then
        local msg='BubbleRob plugin was not found.\nSimulation will not run properly.'
        sim.displayDialog('Error',msg,sim.dlgstyle_ok,true)
    else
        local jointHandles={sim.getObjectHandle('./leftMotor'),sim.getObjectHandle('./rightMotor')}
        local sensorHandle=sim.getObjectHandle('./sensingNose')
        local robHandle=simBubble.create(jointHandles,sensorHandle,{0.5,0.25})
        if robHandle>=0 then
            simBubble.start(robHandle) -- start the robot
            local st=sim.getSimulationTime()
            sim.wait(20) -- run for 20 seconds
            simBubble.stop(robHandle)
            simBubble.destroy(robHandle)
        end
    end
end</pre>

<p>The first part of the code is in charge of checking whether the plugin required to run this script (i.e. <em>simExtBubbleRob.dll</em>) is available (i.e. was found and successfully loaded). If not, an error message is displayed. Otherwise, joint and sensor handles are retrieved and given to the custom Lua function that creates a controller instance of our BubbleRob in the plugin. If the call was successfull, then we can call <em>simBubble.start</em>. The function instructs the plugin to move the BubbleRob model while avoiding obstacles. Run the simulation: BubbleRob moves for 20 seconds then stops, as expected. Now leave CoppeliaSim. Temporarily rename the plugin to <em>TEMP_simExtBubbleRob.dll</em> so that CoppeliaSim won't load it anymore, then start CoppeliaSim again. Load the previous scene and run the simulation: an error message now appears, indicating that the required plugin could not be found. Leave CoppeliaSim again, rename back the plugin to <em>simExtBubbleRob.dll</em> and start CoppeliaSim again.<br>
</p>

<p>Let's have a look at how the plugin registers and handles the above 4 custom Lua functions. Open the <a href="https://github.com/CoppeliaRobotics/simExtBubbleRob" target="_blank">BubbleRob plugin project</a>, and have a look at file <em>simExtBubbleRob.cpp</em>:</p>

<p>Notice the 3 required plugin entry points: <em>simStart</em>, <em>simEnd</em>, and <em>simMessage</em>: <em>simStart</em> is called once when the plugin is loaded (initialization), <em>simEnd</em> is called once when the plugin is unloaded (clean-up), and <em>simMessage</em> is called on a regular basis with several type of messages.</p>

<p>During the initialization phase, the plugin loads the CoppeliaSim library (in order to have access to all CoppeliaSim's API functions), then registers the 4 custom Lua functions. A custom Lua function is registered by specifying:</p>
<li> a function name</li>
<li> a calling tip string</li>
<li> a list of expected arguments </li>
<li> a callback address</li>

<p>When a script calls the specified function name, then CoppeliaSim will try to convert the provided arguments to what is expected by the callback, then calls the callback address. The most difficult task inside of a callback function is to correctly read the input arguments, and correctly write the output values. To ease the task, two helper classes are used, that will be in charge of that: <em>CLuaFunctionData</em> and <em>CLuaFunctionDataItem</em>, located in <em>programming/common</em> and <em>programming/include</em>.</p>
<p>When writing your own custom Lua functions, try to use the same code layout/skeleton as was done in file <em>simExtBubbleRob.cpp</em>.</p>
<p>Control of a BubbleRob instance does not happen in any of the 4 custom Lua function callbacks: the callbacks just initialize/destroy/update data structures. The control happens in <em>simMessage</em>, with message <em>sim_message_eventcallback_modulehandle</em>: that message is called for all plugins when the <a href="mainScript.htm">main script</a> calls <em>sim.handleModule(sim.handle_all,false)</em>, which happens once per simulation pass.</p>






<p>In general, callback routines should execute as fast as possible, and control should then be given back to CoppeliaSim, otherwise the whole simulator will halt.
</p>




<br>
<br>

 </tr>
</table> 
</div>  
  
  
</body>

</html>
